package com.mb.ext.core.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.mb.ext.core.constant.FundConstants;
import com.mb.ext.core.constant.OrderConstants;
import com.mb.ext.core.dao.FileDAO;
import com.mb.ext.core.dao.MerchantDAO;
import com.mb.ext.core.dao.SequenceDAO;
import com.mb.ext.core.dao.SettingDAO;
import com.mb.ext.core.dao.UserBalanceDAO;
import com.mb.ext.core.dao.UserDAO;
import com.mb.ext.core.dao.UserStatementDAO;
import com.mb.ext.core.dao.order.PayOrderDAO;
import com.mb.ext.core.entity.SettingEntity;
import com.mb.ext.core.entity.UserEntity;
import com.mb.ext.core.entity.coupon.CouponEntity;
import com.mb.ext.core.entity.merchant.MerchantEntity;
import com.mb.ext.core.entity.order.PayOrderEntity;
import com.mb.ext.core.message.BusinessErrorCode;
import com.mb.ext.core.service.FundService;
import com.mb.ext.core.service.MerchantService;
import com.mb.ext.core.service.PayOrderService;
import com.mb.ext.core.service.spec.BodyDTO;
import com.mb.ext.core.service.spec.PayOrderSearchDTO;
import com.mb.ext.core.service.spec.UserDTO;
import com.mb.ext.core.service.spec.coupon.CouponDTO;
import com.mb.ext.core.service.spec.merchant.MerchantAssignDTO;
import com.mb.ext.core.service.spec.merchant.MerchantChargeDTO;
import com.mb.ext.core.service.spec.merchant.MerchantDTO;
import com.mb.ext.core.service.spec.order.PayOrderDTO;
import com.mb.framework.exception.BusinessException;
import com.mb.framework.exception.DAOException;
import com.mb.framework.service.AbstractService;
import com.mb.framework.util.DateTimeUtil;
import com.mb.framework.util.log.LogHelper;

@Service
@Qualifier("PayOrderService")
public class PayOrderServiceImpl extends AbstractService implements
		PayOrderService<BodyDTO> {

	@Autowired
	@Qualifier("userDAO")
	private UserDAO userDAO;
	
	@Autowired
	@Qualifier("userStatementDAO")
	private UserStatementDAO userStatementDAO;
	
	@Autowired
	@Qualifier("userBalanceDAO")
	private UserBalanceDAO userBalanceDAO;
	
	@Autowired
	@Qualifier("fileDAO")
	private FileDAO fileDAO;
	
	@Autowired
	@Qualifier("settingDAO")
	private SettingDAO settingDAO;
	
	@Autowired
	@Qualifier("sequenceDAO")
	private SequenceDAO sequenceDAO;

	@Autowired
	@Qualifier("merchantDAO")
	private MerchantDAO merchantDAO;

	@Autowired
	@Qualifier("payOrderDAO")
	private PayOrderDAO payOrderDAO;
	
	@Autowired
	@Qualifier("MerchantService")
	private MerchantService merchantService;

	@Autowired
	@Qualifier("FundService")
	private FundService fundService;

	private final LogHelper logger = LogHelper.getInstance(this.getClass()
			.getName());

	@Override
	public String addPayOrder(PayOrderDTO orderDTO) throws BusinessException {
		try {
			// 1. 添加订单基本信息
			PayOrderEntity orderEntity = new PayOrderEntity();
			String orderNo = getOrderNo();
			orderEntity.setOrderNo(orderNo);
			orderEntity.setOrderTime(new Date());
			orderEntity.setPaymentMethod(orderDTO.getPaymentMethod());
			orderEntity.setWechatPayUuid(orderDTO.getWechatPayUuid());
			orderEntity.setAlipayUuid(orderDTO.getAlipayUuid());
			MerchantDTO merchantDTO = orderDTO.getMerchantDTO();
			MerchantEntity merchantEntity = new MerchantEntity();
			if(merchantDTO != null &&!StringUtils.isEmpty(merchantDTO.getMobileNo())){
				merchantEntity = merchantDAO.getMerchantByMobileNo(merchantDTO.getMobileNo());
			}else{
				merchantEntity = merchantDAO.getMerchantByUuid(merchantDTO.getMerchantUuid());
			}
			if(merchantEntity == null)
				throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR);
			orderEntity.setMerchantEntity(merchantEntity);
			UserDTO userDTO = orderDTO.getUserDTO();
			if(userDTO != null && !StringUtils.isEmpty(userDTO.getUserUuid())){
				UserEntity userEntity = userDAO
						.getUserByUuid(userDTO.getUserUuid());
				orderEntity.setUserEntity(userEntity);
			}
			orderEntity.setOrderStatus(OrderConstants.ORDER_STATUS_NOT_PAYED);
			orderEntity.setProductAmount(orderDTO.getProductAmount());	//商品总金额
			orderEntity.setActualAmount(orderDTO.getActualAmount());	//实付金额
			
			//奖励积分
			BigDecimal productAmount = orderDTO.getProductAmount();
			int exchangeRate = merchantEntity.getExchangeRate();
			int rewardPoint = productAmount.multiply(BigDecimal.valueOf(exchangeRate)).divide(BigDecimal.valueOf(100)).intValue();
			logger.info("本次消费("+orderNo+")获得积分"+rewardPoint);
			orderEntity.setRewardPoint(rewardPoint);
			
			//平台分账金额
			BigDecimal asinfoPlatform = BigDecimal.valueOf(0.00);
			SettingEntity settingEntity = settingDAO.getSettingByName("PLATFORM_EXCHANGE_RATE");	//积分和金额比例, 当前为1元兑换10积分
			if(settingEntity != null) {
				String platformExchangeRateStr = settingEntity.getValue();
				BigDecimal platformExchangeRate = new BigDecimal(platformExchangeRateStr);
				asinfoPlatform = BigDecimal.valueOf(rewardPoint).divide(platformExchangeRate).setScale(2, BigDecimal.ROUND_HALF_UP);
			}
			//商家分账金额
			BigDecimal asinfoMerchant = orderDTO.getProductAmount().subtract(asinfoPlatform);
			orderEntity.setAsinfoMerchant(asinfoMerchant);	//商家分账金额
			orderEntity.setAsinfoPlatform(asinfoPlatform);	//平台分账金额
			
			orderEntity.setCreateBy("system");
			orderEntity.setUpdateBy("system");
			payOrderDAO.addOrder(orderEntity);
			return orderNo;
		} catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,
					e);
		}
	}
	
	public PayOrderDTO getPayOrderByOrderNo(String orderNo) throws BusinessException {
		try {
			PayOrderEntity orderEntity = payOrderDAO.getOrderByOrderNo(orderNo);
			if(orderEntity != null){
				PayOrderDTO orderDTO = new PayOrderDTO();
				payOrderDetailEntity2DTO(orderEntity, orderDTO);
				return orderDTO;
			}else { 
				return null;
			}
		}catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,e);
		}
	}
	
	public PayOrderDTO getPayOrderByUuid(String uuid) throws BusinessException {
		try {
			PayOrderEntity orderEntity = payOrderDAO.getOrderByUuid(uuid);
			if(orderEntity != null){
				PayOrderDTO orderDTO = new PayOrderDTO();
				payOrderDetailEntity2DTO(orderEntity, orderDTO);
				return orderDTO;
			}else { 
				return null;
			}
		}catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,e);
		}
	}
	
	public List<PayOrderDTO> getPayOrderByUser(UserDTO userDTO) throws BusinessException {
		List<PayOrderDTO> orderDTOList = new ArrayList<PayOrderDTO>();
		try {
			UserEntity userEntity = userDAO.getUserByUuid(userDTO.getUserUuid());
			List<PayOrderEntity> orderEntityList = payOrderDAO.getOrdersByUser(userEntity);
			for(Iterator<PayOrderEntity> iter = orderEntityList.iterator();iter.hasNext();){
				PayOrderEntity orderEntity = iter.next();
				PayOrderDTO orderDTO = new PayOrderDTO();
				payOrderDetailEntity2DTO(orderEntity, orderDTO);
				orderDTOList.add(orderDTO);
			}
		}catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,e);
		}
		return orderDTOList;
	}
	
	public List<PayOrderDTO> getPayOrderByMerchant(MerchantDTO merchantDTO) throws BusinessException {
		List<PayOrderDTO> orderDTOList = new ArrayList<PayOrderDTO>();
		try {
			MerchantEntity merchantEntity = merchantDAO.getMerchantByUuid(merchantDTO.getMerchantUuid());
			List<PayOrderEntity> orderEntityList = payOrderDAO.getOrdersByMerchant(merchantEntity);
			for(Iterator<PayOrderEntity> iter = orderEntityList.iterator();iter.hasNext();){
				PayOrderEntity orderEntity = iter.next();
				PayOrderDTO orderDTO = new PayOrderDTO();
				payOrderDetailEntity2DTO(orderEntity, orderDTO);
				orderDTOList.add(orderDTO);
			}
		}catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,e);
		}
		return orderDTOList;
	}
	
	@Override
	public void completePayOrderPay(PayOrderDTO orderDTO) throws BusinessException {
		try {
			PayOrderEntity orderEntity = payOrderDAO.getOrderByOrderNo(orderDTO.getOrderNo());
			//如果是支付宝支付, 更新支付人员ID
			if(OrderConstants.ORDER_PAYMENT_METHOD_ALIPAY.equals(orderEntity.getPaymentMethod()))
				orderEntity.setAlipayUuid(orderDTO.getAlipayUuid());
			else if(OrderConstants.ORDER_PAYMENT_METHOD_WECHAT.equals(orderEntity.getPaymentMethod()))
				orderEntity.setWechatPayUuid(orderDTO.getWechatPayUuid());
			orderEntity.setOutTradeNo(orderDTO.getOutTradeNo());
			orderEntity.setOrderStatus("1");
			payOrderDAO.updateOrder(orderEntity);
		}catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,e);
		}
	}
	
	@Override
	public void receivePayOrderPoint(PayOrderDTO orderDTO) throws BusinessException {
		try {
			PayOrderEntity orderEntity = payOrderDAO.getOrderByOrderNo(orderDTO.getOrderNo());
			if(orderEntity.isRewardPointReceived()) {
				throw new BusinessException(BusinessErrorCode.PAYORDER_POINT_RECEIVE_DUPLICATE);
			}
			UserEntity userEntity = userDAO.getUserByUuid(orderDTO.getUserDTO().getUserUuid());
			UserDTO userDTO = new UserDTO();
			userDTO.setUserUuid(userEntity.getUserUuid());
			
			MerchantEntity merchantEntity = orderEntity.getMerchantEntity();
			MerchantDTO merchantDTO = new MerchantDTO();
			merchantDTO.setMerchantUuid(merchantEntity.getMerchantUuid());
			
/*			//商家充值积分, 为适配手动充值积分, 分解为申请充值和实际充值两部分
			//1. 申请充值
			MerchantChargeDTO merchantChargeDTO = new MerchantChargeDTO();
			merchantChargeDTO.setChargeAmount(orderEntity.getProductAmount());
			merchantChargeDTO.setChargePoint(orderEntity.getRewardPoint());
			merchantChargeDTO.setMerchantDTO(merchantDTO);
			String paymentMethod = orderEntity.getPaymentMethod();
			if(FundConstants.ORDER_PAYMENT_METHOD_WECHAT.equals(paymentMethod))
				merchantChargeDTO.setPaymentMethod(FundConstants.CHARGE_PAYMENT_METHOD_WECHAT);
			if(FundConstants.ORDER_PAYMENT_METHOD_ALIPAY.equals(paymentMethod))
				merchantChargeDTO.setPaymentMethod(FundConstants.CHARGE_PAYMENT_METHOD_ALIPAY);
			String chargeNo = fundService.applyMerchantCharge(merchantChargeDTO);
			//2. 实际充值
			merchantChargeDTO.setChargeNo(chargeNo);
			merchantService.chargePoint(merchantChargeDTO);*/
			
			//划拨积分
			MerchantAssignDTO assignDTO = new MerchantAssignDTO();
			assignDTO.setAssignPoint(orderEntity.getRewardPoint());
			assignDTO.setTranAmount(orderEntity.getProductAmount());
			assignDTO.setMerchantDTO(merchantDTO);
			assignDTO.setUserDTO(userDTO);
			merchantService.assignPoint(assignDTO);
			
			orderEntity.setRewardPointReceived(true);
			orderEntity.setUserEntity(userEntity);
			payOrderDAO.updateOrder(orderEntity);
		}catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,
					e);
		}catch (BusinessException e) {
			throw e;
		}
		
	}
	
	public String getOrderNo() throws BusinessException {
		try {
			int orderNoSequence = sequenceDAO.nextByDate("PAYORDERNO", new Date(),
					null);
			String orderNo = OrderConstants.ORDER_TYPE_PD + DateTimeUtil.formatDateByYYMMDDHHmm(new Date())
					+ StringUtils.leftPad(String.valueOf(orderNoSequence), 4,
							"0");
			return orderNo;
		}catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,
					e);
		}
	}
	
	
	
	private void payOrderDetailEntity2DTO(PayOrderEntity orderEntity,
			PayOrderDTO orderDTO) {
		payOrderEntity2DTO(orderEntity, orderDTO);
		
		
	}
	private void payOrderEntity2DTO(PayOrderEntity orderEntity,
			PayOrderDTO orderDTO) {
		orderDTO.setPayOrderUuid(orderEntity.getPayOrderUuid());
		orderDTO.setOrderNo(orderEntity.getOrderNo());
		orderDTO.setActualAmount(orderEntity.getActualAmount());
		orderDTO.setPaymentMethod(orderEntity.getPaymentMethod());
		orderDTO.setWechatPayUuid(orderEntity.getWechatPayUuid());
		orderDTO.setAlipayUuid(orderEntity.getAlipayUuid());
		MerchantEntity merchantEntity = orderEntity.getMerchantEntity();
		if(merchantEntity != null){
			MerchantDTO merchantDTO = new MerchantDTO();
			merchantDTO.setMerchantUuid(merchantEntity.getMerchantUuid());
			merchantDTO.setMerchantName(merchantEntity.getMerchantName());
			merchantDTO.setMerchantId(merchantEntity.getMerchantId());
			merchantDTO.setMobileNo(merchantEntity.getMobileNo());
			orderDTO.setMerchantDTO(merchantDTO);
		}
		orderDTO.setOrderStatus(orderEntity.getOrderStatus());
		orderDTO.setOrderTime(orderEntity.getOrderTime());
		orderDTO.setOutTradeNo(orderEntity.getOutTradeNo());
		orderDTO.setPaymentTime(orderEntity.getPaymentTime());
		orderDTO.setProductAmount(orderEntity.getProductAmount());
		orderDTO.setAsinfoPlatform(orderEntity.getAsinfoPlatform());
		orderDTO.setAsinfoMerchant(orderEntity.getAsinfoMerchant());
		orderDTO.setRewardPointReceived(orderEntity.isRewardPointReceived());
		orderDTO.setRewardPoint(orderEntity.getRewardPoint());
		UserEntity userEntity = orderEntity.getUserEntity();
		if(userEntity != null){
			UserDTO userDTO = new UserDTO();
			userDTO.setUserUuid(userEntity.getUserUuid());
			userDTO.setName(userEntity.getName());
			userDTO.setPersonalPhone(userEntity.getPersonalPhone());
			orderDTO.setUserDTO(userDTO);
		}
	}

	@Override
	public List<PayOrderDTO> searchPayOrder(PayOrderSearchDTO searchDTO)
			throws BusinessException {
		List<PayOrderDTO> payOrderDTOList = new ArrayList<PayOrderDTO>();
		try{
			List<PayOrderEntity> payOrderEntityList = payOrderDAO.searchPayOrder(searchDTO);
			if(payOrderEntityList != null && !payOrderEntityList.isEmpty()){
				for(Iterator<PayOrderEntity> iter = payOrderEntityList.iterator();iter.hasNext();){
					PayOrderEntity payOrderEntity = iter.next();
					PayOrderDTO payOrderDTO = new PayOrderDTO();
					payOrderDetailEntity2DTO(payOrderEntity,payOrderDTO);
					payOrderDTOList.add(payOrderDTO);
				}
			}
			
		}catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,
					e);
		}
		return payOrderDTOList;
	}

	@Override
	public int searchPayOrderTotal(PayOrderSearchDTO searchDTO)
			throws BusinessException {
		try {
			return payOrderDAO.getPayOrderTotal(searchDTO);
		} catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,
					e);
		}
	}

	@Override
	public BigDecimal getAsinfoPlatformTotal(PayOrderSearchDTO searchDTO)
			throws BusinessException {
		// TODO Auto-generated method stub
		try {
			return payOrderDAO.getAsinfoPlatformTotal(searchDTO);
		} catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,
					e);
		}
	}

	@Override
	public BigDecimal getAsinfoMerchantTotal(PayOrderSearchDTO searchDTO)
			throws BusinessException {
		try {
			return payOrderDAO.getAsinfoMerchantTotal(searchDTO);
		} catch (DAOException e) {
			throw new BusinessException(BusinessErrorCode.COMMON_SYSTEM_ERROR,
					e);
		}
	}
}
